"""
定时刷新扫货账号和订单账号的uk值
"""
import os
import sys
# 将项目根目录添加到Python路径
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(ROOT_DIR)

import time
import schedule
from typing import List, Dict, Any
from datetime import datetime, timedelta
from com.scan_account_pool import ScanAccountPool
from com.db.scan_account_manager import ScanAccountManager
from com.db.order_account_manager import OrderAccountManager
from reqapi.login.device_info_api import DeviceInfoApi, DeviceInfoRequest
from com.utils.logger import get_logger

# 创建logger实例
logger = get_logger(module="账号UK刷新")

class AccountUkRefresher:
    def __init__(self):
        """初始化账号uk刷新器"""
        self.account_pool = ScanAccountPool()
        self.scan_account_manager = ScanAccountManager()
        self.order_account_manager = OrderAccountManager()
        self.account_jobs = {}  # 存储每个账号的定时任务
        
    def _get_active_accounts(self) -> List[Dict[str, Any]]:
        """获取所有有效的账号列表"""
        accounts = []
        try:
            # 获取扫描账号
            scan_accounts = self.scan_account_manager.get_active_accounts()
            for account in scan_accounts:
                accounts.append({
                    'account_type': 'scan',
                    'account': account
                })
                
            # 获取订单账号
            order_accounts = self.order_account_manager.get_active_accounts()
            for account in order_accounts:
                accounts.append({
                    'account_type': 'order',
                    'account': account
                })
                
            return accounts
        except Exception as e:
            logger.error(f"获取有效账号列表失败: {str(e)}")
            return []
    
    def _get_account_availability(self, account_ids: List[int]) -> List[Dict[str, Any]]:
        """获取账号可用列表"""
        try:
            return self.account_pool.get_accounts_by_ids(account_ids)
        except Exception as e:
            logger.error(f"获取账号可用列表失败: {str(e)}")
            return []
    
    def _update_account_uk(self, account_id: int, uk: str, account_type: str):
        """更新账号的uk值"""
        try:
            if account_type == 'scan':
                self.scan_account_manager.update_account_uk(account_id, uk)
            else:
                # 更新订单账号的uk
                self.order_account_manager.update_account(account_id, {
                    'uk': uk,
                    'update_at': int(datetime.now().timestamp() * 1000)
                })
            logger.info(f"{account_type}账号 {account_id} 的uk更新成功: {uk}")
        except Exception as e:
            logger.error(f"更新{account_type}账号 {account_id} 的uk失败: {str(e)}")
    
    def _refresh_uk(self, account_data: Dict[str, Any]):
        """刷新单个账号的uk值"""
        try:
            account_type = account_data['account_type']
            account = account_data['account']
            account_id = account.get('id')
            device_id = account.get('device_id')
            if not device_id:
                logger.warning(f"{account_type}账号 {account_id} 缺少device_id")
                return
            
            # 调用DeviceInfoApi获取新的uk
            api = DeviceInfoApi(
                device_token=device_id,
                device_id=device_id,
                auth_token=account.get('uu_token', ''),  # 使用uu_token作为authorization
                uk=account.get('uk', '')  # 使用account中的uk值
            )
            # 创建请求对象
            request = DeviceInfoRequest.create_default(
                device_id=device_id,
                uk=account.get('uk', ''),
                user_id=account.get('uu_user_id', 0)
            )
            # 发送请求 - 使用custom_report_device_info方法，并指定非首次调用
            response = api.report_device_info(request)
            # 从响应中提取uk值
            uk = response.data.get('uk', '')
            
            if uk:
                # 更新账号uk和设备ID
                self._update_account_uk(account_id, uk, account_type)
                
                # 重新获取账号可用状态
                if account_type == 'scan':
                    account_status = self._get_account_availability([account_id])
                    if account_status:
                        # 更新下次刷新时间（当前可用时间 + 6小时）
                        next_time = account_status[0]['next_available_time'] + 21600  # 6小时 = 6 * 60 * 60 = 21600秒
                        logger.info(f"{account_type}账号 {account_id} 下次刷新时间: {datetime.fromtimestamp(next_time).strftime('%Y-%m-%d %H:%M:%S')}")
                        
                        # 重新设置定时任务
                        self._schedule_account_refresh(account_data, next_time)
                else:
                    # 订单账号固定6小时后刷新
                    next_time = time.time() + 21600  # 6小时 = 6 * 60 * 60 = 21600秒
                    logger.info(f"{account_type}账号 {account_id} 下次刷新时间: {datetime.fromtimestamp(next_time).strftime('%Y-%m-%d %H:%M:%S')}")
                    self._schedule_account_refresh(account_data, next_time)
            else:
                logger.error(f"{account_type}账号 {account_id} 获取uk失败")
        except Exception as e:
            logger.error(f"刷新{account_type}账号 {account.get('id')} 的uk时发生错误: {str(e)}")
    
    def _schedule_account_refresh(self, account_data: Dict[str, Any], next_time: float):
        """为账号设置下次刷新时间"""
        account_id = account_data['account'].get('id')
        
        # 如果账号已有定时任务，先取消
        if account_id in self.account_jobs:
            schedule.cancel_job(self.account_jobs[account_id])
        
        # 计算延迟时间（秒）
        delay = max(0, next_time - time.time())
        
        # 创建一次性定时任务
        job = schedule.every(delay).seconds.do(self._refresh_uk, account_data)
        self.account_jobs[account_id] = job
    
    def refresh_all_accounts(self):
        """刷新所有账号的uk值"""
        logger.info(f"开始初始化账号uk刷新任务 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        
        # 1. 获取所有有效账号
        active_accounts = self._get_active_accounts()
        if not active_accounts:
            logger.warning("没有找到有效账号")
            return
        
        # 2. 为每个账号设置刷新任务
        for account_data in active_accounts:
            account_type = account_data['account_type']
            account = account_data['account']
            account_id = account.get('id')
            
            if account_type == 'scan':
                # 扫描账号需要检查可用性
                account_status = self._get_account_availability([account_id])
                if account_status:
                    # 更新下次刷新时间（当前可用时间 + 6小时）
                    next_time = account_status[0]['next_available_time'] + 21600  # 6小时 = 6 * 60 * 60 = 21600秒
                    logger.info(f"{account_type}账号 {account_id}:")
                    logger.info(f"初始刷新时间: {datetime.fromtimestamp(next_time).strftime('%Y-%m-%d %H:%M:%S')}")
                    
                    # 设置定时任务
                    self._schedule_account_refresh(account_data, next_time)
            else:
                # 订单账号固定6小时后刷新
                next_time = time.time() + 21600  # 6小时 = 6 * 60 * 60 = 21600秒
                logger.info(f"{account_type}账号 {account_id}:")
                logger.info(f"初始刷新时间: {datetime.fromtimestamp(next_time).strftime('%Y-%m-%d %H:%M:%S')}")
                
                # 设置定时任务
                self._schedule_account_refresh(account_data, next_time)
    
    def start(self):
        """启动定时刷新任务"""
        logger.info("启动账号uk定时刷新任务...")
        
        # 初始化所有账号的刷新任务
        self.refresh_all_accounts()
        
        # 持续运行定时任务
        while True:
            try:
                schedule.run_pending()
                time.sleep(1)
            except KeyboardInterrupt:
                logger.info("停止账号uk定时刷新任务")
                break
            except Exception as e:
                logger.error(f"定时任务执行出错: {str(e)}")
                time.sleep(5)  # 出错后等待5秒再继续
    
    def start_background_refresh(self):
        """在后台启动uk刷新任务"""
        import threading
        
        def run_scheduler():
            self.refresh_all_accounts()
            while not getattr(self, '_stop_flag', False):
                schedule.run_pending()
                time.sleep(1)
        
        # 创建后台线程
        self._stop_flag = False
        self.refresh_thread = threading.Thread(target=run_scheduler)
        self.refresh_thread.daemon = True  # 设置为守护线程
        self.refresh_thread.start()
        logger.info("账号UK刷新器后台线程已启动")
    
    def stop(self):
        """停止uk刷新任务"""
        self._stop_flag = True
        if hasattr(self, 'refresh_thread'):
            self.refresh_thread.join(timeout=2)  # 等待线程结束，最多等待2秒
        logger.info("账号UK刷新器已停止")
        
    def test_uk_refresh(self, account_id: int, account_type: str = 'scan'):
        """测试UK刷新功能，直接调用内部的_refresh_uk方法
        
        Args:
            account_id: 账号ID
            account_type: 账号类型，'scan'或'order'，默认为'scan'
        """
        try:
            # 获取账号信息
            account = None
            if account_type == 'scan':
                account = self.scan_account_manager.get_account_by_id(account_id)
            else:
                account = self.order_account_manager.get_account_by_id(account_id)
                
            if not account:
                print(f"未找到{account_type}账号 {account_id}")
                return
                
            # 打印账号原始信息
            print(f"\n{'='*50}")
            print(f"测试{account_type}账号 {account_id} 的UK刷新")
            print(f"{'='*50}")
            print(f"账号原始信息:")
            print(f"  设备ID: {account.get('device_id', '')}")
            print(f"  原始UK: {account.get('uk', '')}")
            print(f"  用户ID: {account.get('uu_user_id', '')}")
            
            # 创建账号数据结构
            account_data = {
                'account_type': account_type,
                'account': account
            }
            
            # 调用内部的_refresh_uk方法
            print(f"\n开始调用_refresh_uk方法...")
            self._refresh_uk(account_data)
            
            # 重新获取账号信息，检查UK是否已更新
            if account_type == 'scan':
                updated_account = self.scan_account_manager.get_account_by_id(account_id)
            else:
                updated_account = self.order_account_manager.get_account_by_id(account_id)
                
            print(f"\nUK比对结果:")
            print(f"  原始UK: {account.get('uk', '')}")
            print(f"  更新后UK: {updated_account.get('uk', '')}")
            
            if account.get('uk', '') != updated_account.get('uk', ''):
                print(f"\n结果: UK值已成功更新")
            else:
                print(f"\n结果: UK值未变化")
                
        except Exception as e:
            print(f"测试过程中发生错误: {str(e)}")

def init_account_uk_refresh():
    """初始化账号uk刷新器"""
    refresher = AccountUkRefresher()
    return refresher.start_background_refresh()

# 测试函数
def test_uk_refresh_function(account_id: int, account_type: str = 'scan'):
    """测试UK刷新功能
    
    Args:
        account_id: 账号ID
        account_type: 账号类型，'scan'或'order'，默认为'scan'
    """
    refresher = AccountUkRefresher()
    refresher.test_uk_refresh(account_id, account_type)

if __name__ == "__main__":
    # 如果有命令行参数，则运行测试
    if len(sys.argv) > 1:
        if sys.argv[1] == 'test':
            account_id = int(sys.argv[2]) if len(sys.argv) > 2 else 1
            account_type = sys.argv[3] if len(sys.argv) > 3 else 'scan'
            # 直接运行测试，不启动定时器
            test_uk_refresh_function(account_id, account_type)
            # 测试完成后直接退出
            sys.exit(0)
        else:
            init_account_uk_refresh()
            while True:
                time.sleep(1)
    else:
        init_account_uk_refresh()
        while True:
            time.sleep(1)
